#include "common.hpp"
#include <mutex>

// 1. ------单例模式------
// 1.1 饿汉式
// class Singleton
// {
// public:
//     static Singleton* getinstance()
//     {
//         return instance;
//     }
//     void print()
//     {
//         cout<<"This is a hungry singleton."<<endl;
//         cout<<"this:"<<this<<endl;
//     }
// private:
//     Singleton() {}
//     Singleton(const Singleton&) = default;
//     Singleton& operator=(const Singleton&) = default;

//     static Singleton* instance;
// };
// Singleton* Singleton::instance = new Singleton();

//1.2 懒汉式
// class Singleton
// {
// public:
//     static Singleton* getinstance()
//     {
//         if(instance == nullptr)
//         {
//             mtx.lock();
//             if(instance == nullptr)
//             {
//                 instance = new Singleton();
//             }
//             mtx.unlock();
//         }
//         return instance;
//     }
//     void print()
//     {
//         cout<<"This is a lazy singleton."<<endl;
//         cout<<"this:"<<this<<endl;
//     }
// private:
//     Singleton(){};
//     Singleton(const Singleton&) = default;
//     Singleton& operator=(const Singleton&) = default;

//     static Singleton* instance;
//     static std::mutex mtx;
// };
// Singleton* Singleton::instance = nullptr;
// std::mutex Singleton::mtx;
// int main()
// {
//     Singleton* s1 = Singleton::getinstance();
//     s1->print();
//     Singleton* s2 = Singleton::getinstance();
//     s2->print();
//     return 0;

// }



// 双重检查锁定的问题
// 实际上 m_taskQ = new TaskQueue; 在执行过程中对应的机器指令可能会被重新排序。正常过程如下：
// 第一步：分配内存用于保存 TaskQueue 对象。
// 第二步：在分配的内存中构造一个 TaskQueue 对象（初始化内存）。
// 第三步：使用 m_taskQ 指针指向分配的内存。
// 但是被重新排序以后执行顺序可能会变成这样：
// 第一步：分配内存用于保存 TaskQueue 对象。
// 第二步：使用 m_taskQ 指针指向分配的内存。
// 第三步：在分配的内存中构造一个 TaskQueue 对象（初始化内存）。
// 这样重排序并不影响单线程的执行结果，但是在多线程中就会出问题。
// 如果线程A按照第二种顺序执行机器指令，执行完前两步之后失去CPU时间片被挂起了，
// 此时线程B在第3行处进行指针判断的时候m_taskQ 指针是不为空的，
// 但这个指针指向的内存却没有被初始化，最后线程 B 使用了一个没有被初始化的队列对象就出问题了


// 在C++11中引入了原子变量atomic，通过原子变量可以实现一种更安全的懒汉模式的单例，代码如下：
// class TaskQueue
// {
// public:
//     // = delete 代表函数禁用, 也可以将其访问权限设置为私有
//     TaskQueue(const TaskQueue& obj) = delete;
//     TaskQueue& operator=(const TaskQueue& obj) = delete;
//     static TaskQueue* getInstance()
//     {
//         TaskQueue* queue = m_taskQ.load();  // load-->取出原子变量的值
//         if (queue == nullptr)
//         {
//             // m_mutex.lock();  // 加锁: 方式1
//             lock_guard<mutex> locker(m_mutex);  // 加锁: 方式2
//             queue = m_taskQ.load();
//             if (queue == nullptr)
//             {
//                 queue = new TaskQueue;
//                 m_taskQ.store(queue);  // store-->将原子变量的值设置为queue
//             }
//             // m_mutex.unlock();
//         }
//         return queue;
//     }

//     void print()
//     {
//         cout << "hello, world!!!" << endl;
//     }
// private:
//     TaskQueue() = default;
//     static atomic<TaskQueue*> m_taskQ;
//     static mutex m_mutex;
// };
// atomic<TaskQueue*> TaskQueue::m_taskQ;
// mutex TaskQueue::m_mutex;

// int main()
// {
//     TaskQueue* queue = TaskQueue::getInstance();
//     queue->print();
//     return 0;
// }


// 单例模式 -- 写一个任务队列
// 属性：
// 存储任务的容器，这个容器可以选择使用STL中的队列（queue)
// 互斥锁，多线程访问的时候用于保护任务队列中的数据
// 方法：主要是对任务队列中的任务进行操作
// 任务队列中任务是否为空
// 往任务队列中添加一个任务
// 从任务队列中取出一个任务
// 从任务队列中删除一个任务




// class TaskQueue
// {
// public:
//     // = delete 代表函数禁用, 也可以将其访问权限设置为私有
//     TaskQueue(const TaskQueue& obj) = delete;
//     TaskQueue& operator=(const TaskQueue& obj) = delete;
//     static TaskQueue* getInstance()
//     {
//         return &m_obj;
//     }
//     // 任务队列是否为空
//     bool isEmpty()
//     {
//         lock_guard<mutex> locker(m_mutex);
//         bool flag = m_taskQ.empty();
//         return flag;
//     }
//     // 添加任务
//     void addTask(int data)
//     {
//         lock_guard<mutex> locker(m_mutex);
//         m_taskQ.push(data);
//     }
//     // 取出一个任务
//     int takeTask()
//     {
//         lock_guard<mutex> locker(m_mutex);
//         if (!m_taskQ.empty())
//         {
//             return m_taskQ.front();
//         }
//         return -1;
//     }
//     // 删除一个任务
//     bool popTask()
//     {
//         lock_guard<mutex> locker(m_mutex);
//         if (!m_taskQ.empty())
//         {
//             m_taskQ.pop();
//             return true;
//         }
//         return false;
//     }
// private:
//     TaskQueue() = default;
//     static TaskQueue m_obj;
//     queue<int> m_taskQ;
//     mutex m_mutex;
// };
// TaskQueue TaskQueue::m_obj;

// int main()
// {
//     thread t1([]() {
//         TaskQueue* taskQ = TaskQueue::getInstance();
//         for (int i = 0; i < 100; ++i)
//         {
//             taskQ->addTask(i + 100);
//             cout << "+++push task: " << i + 100 << ", threadID: " 
//                 << this_thread::get_id() << endl;
//             this_thread::sleep_for(chrono::milliseconds(500));
//         }
//     });
//     thread t2([]() {
//         TaskQueue* taskQ = TaskQueue::getInstance();
//         this_thread::sleep_for(chrono::milliseconds(100));
//         while (!taskQ->isEmpty())
//         {
//             int data = taskQ->takeTask();
//             cout << "---take task: " << data << ", threadID: " 
//                 << this_thread::get_id() << endl;
//             taskQ->popTask();
//             this_thread::sleep_for(chrono::seconds(1));
//         }
//     });
//     t1.join();
//     t2.join();
// }





// 2. ------工厂模式------
// 2.1 简单工厂模式  对多态的应用

// 不论使用哪种工厂模式其主要目的都是实现类与类之间的解耦合，这样我们在创建对象的时候就变成了拿来主义，使程序更加便于维护。
// 基于简单工厂模式去创建对象的时候，需要提供一个工厂类，专门用于生产需要的对象，这样关于对象的创建操作就被剥离出去了。

// 简单工厂模式相关类的创建和使用步骤如下：

// 创建一个新的类, 可以将这个类称之为工厂类。对于简单工厂模式来说，需要的工厂类只有一个。
// 在这个工厂类中添加一个公共的成员函数，通过这个函数来创建我们需要的对象，关于这个函数一般将其称之为工厂函数。
// 关于使用，首先创建一个工厂类对象，然后通过这个对象调用工厂函数，这样就可以生产出一个指定类型的实例对象了。

// // 人造恶魔果实· 绵羊形态
// class SheepSmile
// {
// public:
//     void transform()
//     {
//         cout << "变成人兽 -- 山羊人形态..." << endl;
//     }
//     void ability()
//     {
//         cout << "将手臂变成绵羊角的招式 -- 巨羊角" << endl;
//     }
// };

// // 人造恶魔果实· 狮子形态
// class LionSmile
// {
// public:
//     void transform()
//     {
//         cout << "变成人兽 -- 狮子人形态..." << endl;
//     }
//     void ability()
//     {
//         cout << "火遁· 豪火球之术..." << endl;
//     }
// };

// // 人造恶魔果实· 蝙蝠形态
// class BatSmile
// {
// public:
//     void transform()
//     {
//         cout << "变成人兽 -- 蝙蝠人形态..." << endl;
//     }
//     void ability()
//     {
//         cout << "声纳引箭之万剑归宗..." << endl;
//     }
// };

// enum class Type:char{SHEEP, LION, BAT};
// // 恶魔果实工厂类
// class SmileFactory
// {
// public:
//     enum class Type:char{SHEEP, LION, BAT};
//     SmileFactory() {}
//     ~SmileFactory() {}
//     void* createSmile(Type type)
//     {
//         void* ptr = nullptr;
//         switch (type)
//         {
//         case Type::SHEEP:
//             ptr = new SheepSmile;
//             break;
//         case Type::LION:
//             ptr = new LionSmile;
//             break;
//         case Type::BAT:
//             ptr = new BatSmile;
//             break;
//         default:
//             break;
//         }
//         return ptr;
//     }
// };

// int main()
// {
//     SmileFactory* factory = new SmileFactory;
//     BatSmile* batObj = (BatSmile*)factory->createSmile(Type::BAT);
//     return 0;
// }


// class AbstractSmile
// {
// public:
//     virtual void transform() {}
//     virtual void ability() {}
//     virtual ~AbstractSmile() {}
// };
// // 人造恶魔果实· 绵羊形态
// class SheepSmile : public AbstractSmile
// {
// public:
//     void transform() override
//     {
//         cout << "变成人兽 -- 山羊人形态..." << endl;
//     }
//     void ability() override
//     {
//         cout << "将手臂变成绵羊角的招式 -- 巨羊角" << endl;
//     }
// };

// // 人造恶魔果实· 狮子形态
// class LionSmile : public AbstractSmile
// {
// public:
//     void transform() override
//     {
//         cout << "变成人兽 -- 狮子人形态..." << endl;
//     }
//     void ability() override
//     {
//         cout << "火遁· 豪火球之术..." << endl;
//     }
// };

// class BatSmile : public AbstractSmile
// {
// public:
//     void transform() override
//     {
//         cout << "变成人兽 -- 蝙蝠人形态..." << endl;
//     }
//     void ability() override
//     {
//         cout << "声纳引箭之万剑归宗..." << endl;
//     }
// };

// // 恶魔果实工厂类
// enum class Type:char{SHEEP, LION, BAT};
// class SmileFactory
// {
// public:
//     SmileFactory() {}
//     ~SmileFactory() {}
//     AbstractSmile* createSmile(Type type)
//     {
//         AbstractSmile* ptr = nullptr;
//         switch (type)
//         {
//         case Type::SHEEP:
//             ptr = new SheepSmile;
//             break;
//         case Type::LION:
//             ptr = new LionSmile;
//             break;
//         case Type::BAT:
//             ptr = new BatSmile;
//             break;
//         default:
//             break;
//         }
//         return ptr;
//     }
// };

// int main()
// {
//     SmileFactory* factory = new SmileFactory;
//     //AbstractSmile* obj = factory->createSmile(Type::BAT);
//     AbstractSmile* obj = factory->createSmile(Type::LION);
//     obj->transform();
//     obj->ability();
//     return 0;
// }




// 2.2 工厂方法模式  适用于创建复杂的对象
// 在上面的工厂函数中需要生成三种人造恶魔果实，现在如果想要生成更多，
// 那么就需要在工厂函数的switch语句中添加更多的case，
// 很明显这违背了封闭原则，也就意味着需要基于开放原则来解决这个问题。

// 使用工厂模式可以很完美的解决上述的问题，简单工厂模式是只有一个工厂类，而工厂模式是有很多的工厂类：

// 一个基类，包含一个虚工厂函数，用于实现多态。
// 多个子类，重写父类的工厂函数。
// 每个子工厂类负责生产一种恶魔果实，这相当于再次解耦，
// 将工厂类的职责再次拆分、细化，如果要生产新品种的恶魔果实，
// 那么只需要添加对应的工厂类，无需修改原有的代码。



// class AbstractSmile
// {
// public:
//     virtual void transform() = 0;
//     virtual void ability() = 0;
//     virtual ~AbstractSmile() {}
// };
// // 人造恶魔果实· 绵羊形态
// class SheepSmile : public AbstractSmile
// {
// public:
//     void transform() override
//     {
//         cout << "变成人兽 -- 山羊人形态..." << endl;
//     }
//     void ability() override
//     {
//         cout << "将手臂变成绵羊角的招式 -- 巨羊角" << endl;
//     }
// };

// // 人造恶魔果实· 狮子形态
// class LionSmile : public AbstractSmile
// {
// public:
//     void transform() override
//     {
//         cout << "变成人兽 -- 狮子人形态..." << endl;
//     }
//     void ability() override
//     {
//         cout << "火遁· 豪火球之术..." << endl;
//     }
// };

// class BatSmile : public AbstractSmile
// {
// public:
//     void transform() override
//     {
//         cout << "变成人兽 -- 蝙蝠人形态..." << endl;
//     }
//     void ability() override
//     {
//         cout << "声纳引箭之万剑归宗..." << endl;
//     }
// };

// // 恶魔果实工厂类
// class AbstractFactory
// {
// public:
//     virtual AbstractSmile* createSmile() = 0;
//     virtual ~AbstractFactory() {}
// };

// class SheepFactory : public AbstractFactory
// {
// public:
//     AbstractSmile* createSmile() override
//     {
//         return new SheepSmile;
//     }
//     ~SheepFactory()
//     {
//         cout << "释放 SheepFactory 类相关的内存资源" << endl;
//     }
// };

// class LionFactory : public AbstractFactory
// {
// public:
//     // 工厂函数
//     AbstractSmile* createSmile() override
//     {
//         return new LionSmile;
//     }
//     ~LionFactory()
//     {
//         cout << "释放 LionFactory 类相关的内存资源" << endl;
//     }

// };

// class BatFactory : public AbstractFactory
// {
// public:
//     // 工厂函数
//     AbstractSmile* createSmile() override
//     {
//         return new BatSmile;
//     }
//     ~BatFactory()
//     {
//         cout << "释放 BatFactory 类相关的内存资源" << endl;
//     }
// };

// int main()
// {
//     AbstractFactory* factory = new BatFactory;
//     AbstractSmile* obj = factory->createSmile();
//     obj->transform();
//     obj->ability();

//     delete obj;
//     delete factory;

//     return 0;
// }


// 2.3 抽象工厂模式  适用于创建复杂的对象
// 船体
class ShipBody
{
public:
    virtual string getShipBody() = 0;
    virtual ~ShipBody() {}
};

class WoodBody : public ShipBody
{
public:
    string getShipBody() override
    {
        return string("用<木材>制作轮船船体...");
    }
};

class IronBody : public ShipBody
{
public:
    string getShipBody() override
    {
        return string("用<钢铁>制作轮船船体...");
    }
};

class MetalBody : public ShipBody
{
public:
    string getShipBody() override
    {
        return string("用<合金>制作轮船船体...");
    }
};

// 动力
class Engine
{
public:
    virtual string getEngine() = 0;
    virtual ~Engine() {}
};

class Human : public Engine
{
public:
    string getEngine() override
    {
        return string("使用<人力驱动>...");
    }
};

class Diesel : public Engine
{
public:
    string getEngine() override
    {
        return string("使用<内燃机驱动>...");
    }
};

class Nuclear : public Engine
{
public:
    string getEngine() override
    {
        return string("使用<核能驱动>...");
    }
};

// 武器
class Weapon
{
public:
    virtual string getWeapon() = 0;
    virtual ~Weapon() {}
};

class Gun : public Weapon
{
public:
    string getWeapon() override
    {
        return string("配备的武器是<枪>");
    }
};

class Cannon : public Weapon
{
public:
    string getWeapon() override
    {
        return string("配备的武器是<自动机关炮>");
    }
};

class Laser : public Weapon
{
public:
    string getWeapon() override
    {
        return string("配备的武器是<激光>");
    }
};

// 轮船类
class Ship
{
public:
    Ship(ShipBody* body, Weapon* weapon, Engine* engine) :
        m_body(body), m_weapon(weapon), m_engine(engine) 
    {
    }
    string getProperty()
    {
        string info = m_body->getShipBody() + m_weapon->getWeapon() + m_engine->getEngine();
        return info;
    }
    ~Ship() 
    {
        delete m_body;
        delete m_engine;
        delete m_weapon;
    }
private:
    ShipBody* m_body = nullptr;
    Weapon* m_weapon = nullptr;
    Engine* m_engine = nullptr;
};


// 工厂类
class AbstractFactory
{
public:
    virtual Ship* createShip() = 0;
    virtual ~AbstractFactory() {}
};

class BasicFactory : public AbstractFactory
{
public:
    Ship* createShip() override
    {
        Ship* ship = new Ship(new WoodBody, new Gun, new Human);
        cout << "<基础型>战船生产完毕, 可以下水啦..." << endl;
        return ship;
    }
};

class StandardFactory : public AbstractFactory
{
public:
    Ship* createShip() override
    {
        Ship* ship = new Ship(new IronBody, new Cannon, new Diesel);
        cout << "<标准型>战船生产完毕, 可以下水啦..." << endl;
        return ship;
    }
};

class UltimateFactory : public AbstractFactory
{
public:
    Ship* createShip() override
    {
        Ship* ship = new Ship(new MetalBody, new Laser, new Nuclear);
        cout << "<旗舰型>战船生产完毕, 可以下水啦..." << endl;
        return ship;
    }
};

int main()
{
    //AbstractFactory* factroy = new StandardFactory;
    AbstractFactory* factroy = new UltimateFactory;
    Ship* ship = factroy->createShip();
    cout << ship->getProperty();
    delete ship;
    delete factroy;
    return 0;
}
